#!/usr/bin/env python
# _*_coding:utf-8 _*_
__author__ = "Gao"
from django.forms import forms
from django.forms import ModelForm
from django.forms import ValidationError
from django.utils.translation import ugettext as _    # 支持国际化
from django import forms
from django.forms import fields
from django.forms import ValidationError
from django.forms import widgets
from django.conf import settings
from django.contrib.auth import hashers

from crm import models


hasher = getattr(hashers,settings.AUTH_HASHER)


def create_model_form(request, admin_class, is_add_form=False):
    '''动态生成model_form'''

    def __new__(cls, *args, **kwargs):
        def set_field(field_name):
            if not is_add_form:
                # 做修改操作时，给只读字段添加disabled属性
                if field_name in admin_class.readonly_fields:
                    field_obj.widget.attrs['disabled'] = 'disabled'

        if (admin_class.model._meta.app_label + '.' + admin_class.model.__name__) == settings.AUTH_USER_MODEL:
            for field_name, field_obj in cls.base_fields.items():    # 给字段添加样式
                if field_name == cls.Meta.model.PASSWORD_FIELD:    # 对密码字段做额外配置
                    if is_add_form:
                        field_obj.widget = forms.PasswordInput(attrs={'class': 'form-control'})
                        field_obj.help_text = ''
                    else:
                        field_obj.widget.attrs['class'] = 'form-control'
                elif 'BooleanField' in field_obj.__repr__():
                    pass
                else:
                    field_obj.widget.attrs['class'] = 'form-control'
                set_field(field_name)
        else:
            for field_name, field_obj in cls.base_fields.items():    # 给字段添加样式
                if 'BooleanField' in field_obj.__repr__():
                    pass
                else:
                    field_obj.widget.attrs['class'] = 'form-control'
                set_field(field_name)

        return ModelForm.__new__(cls)


    def default_clean(self):
        '''给所有的form添加一个clean验证'''
        error_list = []
        # 判断是否是只读表
        if admin_class.readonly_table:
            error_list.append(ValidationError(
                _('该表不可被修改'),
                code='400',
            ))
        # 修改操作时，验证只读字段
        if self.instance.id:
            for field in admin_class.readonly_fields:
                new_field = self.cleaned_data.get(field)    # 前端传来的数据
                field_val = getattr(self.instance, field)    # 数据库中读取的数据
                # 对m2m字段做验证
                if hasattr(field_val,'all'):
                    m2m_objs = getattr(field_val,'all')()
                    m2m_vals = [(i[0]) for i in m2m_objs.values_list('id') ]
                    set_m2m_vals = set(m2m_vals)    # 数据库中的数据
                    new_m2m_vals = set(i.id for i in self.cleaned_data.get(field))    # 前端传入的数据
                    if set_m2m_vals != new_m2m_vals:
                        self.add_error(field, '该项只读,不可修改')
                        print(dir(field_val))
                elif new_field != field_val:
                    error_list.append( ValidationError(
                        _('%(field)s是只读的，值应该为:%(val)s'),
                        code='400',
                        params={'field':field,'val': field_val}
                    ))

        elif (self.instance._meta.app_label + '.' + self.instance.__class__.__name__) == settings.AUTH_USER_MODEL:
            # 创建账号时，对密码做加密处理
            self.cleaned_data[self.instance.PASSWORD_FIELD] = hasher.encode(hasher,
                                                                    self.cleaned_data[self.instance.PASSWORD_FIELD],
                                                                    hasher.salt(hasher))
        res = admin_class.default_form_validation(self)  # 执行自定义的form验证
        if res:
            error_list.append(res)
        if error_list:
            raise ValidationError(error_list)
        return self.cleaned_data

    class Meta:
        model = admin_class.model    # 关联model
        fields = '__all__'
        exclude = admin_class.modelform_exclude_fields    # 不显示指定字段






    attrs = {'Meta': Meta,
             '__new__':__new__,
             'clean': default_clean}
    _model_form_class = type('DynamicModelClass',(ModelForm,), attrs)    # 使用type动态创建model_form类

    return _model_form_class


class PasswordResetForm(forms.Form):
    '''修改密码form验证'''
    password1 = fields.CharField(
        widget=widgets.PasswordInput(attrs={'class': "form-control",'placeholder': '请输入密码'}),
        required=True,
        min_length=4,
        error_messages={'required': '密码不能为空!', 'min_length': '密码最少为4个字符'},
        label='密码:'
    )

    password2 = fields.CharField(
        widget=widgets.PasswordInput(attrs={'class': "form-control",'placeholder': '请重新输入密码'}),
        required=True,
        min_length=4,
        error_messages={'required': '密码不能为空!','min_length': '密码最少为4个字符'},
        label='密码(重复):'
    )

    def clean(self):
        if not self.cleaned_data['password1'].strip() or not \
            self.cleaned_data['password1'].strip() == self.cleaned_data['password2'].strip():
            raise ValidationError('两次输入密码不一致')
        return self.cleaned_data
